package com.kotlin.base.net

import android.app.Activity
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import com.drake.net.Get
import com.drake.net.exception.ConvertException
import com.drake.net.exception.RequestParamsException
import com.drake.net.exception.ServerResponseException
import com.drake.net.utils.scope
import com.kotlin.base.di.getError
import com.kotlin.base.di.getNetwork
import com.kotlin.base.err.*
import com.tao.data.Resource

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import org.json.JSONException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.util.concurrent.TimeoutException

fun <T> ViewModel.request(
    flow: Flow<T>,
    stateFlow: MutableStateFlow<Resource<T>>,
    witch: Int = 0
) {
   viewModelScope.request(flow, stateFlow, witch)
}



fun <T> CoroutineScope.request(
    flow: Flow<T>,
    stateFlow: MutableStateFlow<Resource<T>>,
    witch: Int = 0
) {
    //请求之前操作
    val network = getNetwork()
    if (!network.isConnected()) {
        // 无网络
        val errors = getError()

        stateFlow.update {
          value->
            Resource.Error(witch, errors.getError(ERROR_NO_INTERNET))
        }
        return
    }
   // stateFlow.value = Resource.Start(witch)
    this.launch {


        //网络请求
        flow.catch { // 异常
            //Get<>()// 捕获处理
            //XLog.e("Exception", it)
            val errors = getError()
            val error = when (it) {
                // 连接超时
                is ConnectException,
                    // Socket网络异常
                is SocketTimeoutException,
                    // 数据解析异常
                is JSONException,
                    // 请求超时
                is TimeoutException -> errors.getError(ERROR_REQUEST)
                is HttpException -> {
                    // non-2xx HTTP response
                    val he = it as HttpException
                    errors.getError(he.code(), he.message())
                }
                is ServerResponseException -> {
                    // todo 处理服务端自定义code
                    val se = it as ServerResponseException
                    errors.getError(se.response.code,se.message?:"服务器异常")
                }
                is RequestParamsException ->{

                    //请求参数异常
                    val re = it as RequestParamsException

                    errors.getError(re.response.code,re.message?:"请求参数异常")


                }

                is ConvertException -> {

                    val ce =it as ConvertException

                    errors.getError(ce.response.code,ce.message?:"转换异常")
                }

                else -> {
//                    it.message ?: errors.getError(ERROR_UNKNOWN)
                    it.message?.let {cause ->
                        // msg不为空
                        errors.getError(ERROR_UNKNOWN, cause)
                    } ?: errors.getError(ERROR_UNKNOWN) // msg为空
                }
            }
           // emit()
            stateFlow.update {
                value->
                Resource.Error(witch, error)

            }


        }
            //数据请求返回处理
            .collect {
                stateFlow.value = Resource.Success(witch, it)
            }
    }
}
//.onCompletion {
//                // 结束
//                stateFlow.value = Resource.Complete(witch)
//            }


// fun Fragment.addObservice( block:()->Unit)=lifecycleScope.launch {
//
//    repeatOnLifecycle(Lifecycle.State.STARTED){
//        block()
//    }
//
//}
//fun Fragment.addObservice( block:suspend CoroutineScope.() -> Unit)= viewLifecycleOwner.lifecycleScope.apply {
//
//    launch {
//        viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED){
//            block()
//        }
//
//    }
//
//}
fun Fragment.addObservice( block:suspend CoroutineScope.() -> Unit)= viewLifecycleOwner.lifecycleScope.apply {
      launchWhenStarted {
          block()
      }
}

fun AppCompatActivity.addObservice( block:suspend CoroutineScope.() -> Unit)= lifecycleScope.apply {

    launch {
        repeatOnLifecycle(Lifecycle.State.STARTED){
            block()
        }
        repeatOnLifecycle(Lifecycle.State.RESUMED){
            block()
        }
    }

}






